"""
plugin_manager.py
插件模式是一种软件设计模式，它允许软件系统通过扩展一个应用程序的功能来增强可扩展性和灵活性。
它允许应用程序在运行时动态加载模块（插件），而不需要在编译时指定这些模块。这种模式允许应用程序扩展其功能，而无需修改其源代码或重新编译。
"""

import importlib  # 使用importlib库导入Python库中的插件


PluginsList = ['model_plugin_1',
               'model_plugin_2',
               'view_plugin_1',
               'view_plugin_2',
               'controller_plugin_1',
               'controller_plugin_2']


# 创建一个基础插件接口类，定义插件类型、名称、描述和版本号等信息
class PluginBase:
    PLUGIN_TYPE = None
    PLUGIN_NAME = None
    PLUGIN_DESCRIPTION = None
    PLUGIN_VERSION = None

    def activate(self):

        pass

    def deactivate(self):
        pass


# 定义具体的插件类型，即Model类型、View类型、Controller类型。
# 每个插件类型都需要从PluginBase类继承，并重写PLUGIN_TYPE属性。
class ModelPlugin(PluginBase):
    PLUGIN_TYPE = 'Model'


class ViewPlugin(PluginBase):
    PLUGIN_TYPE = 'View'


class ControllerPlugin(PluginBase):
    PLUGIN_TYPE = 'Controller'


# 实现一个插件管理器类，这个类将负责加载和卸载插件。
class PluginManager:
    def __init__(self):
        self.plugins = dict()

    def load_plugin(self, name):
        if name in self.plugins:
            return
        module = importlib.import_module(name)
        plugin = module.Plugin()
        self.plugins[name] = plugin
        plugin.activate()
        for name_, plugin_ in self.plugins.items():
            if type(plugin).PLUGIN_TYPE == type(plugin_).PLUGIN_TYPE and plugin_ != plugin:
                self.delPulginName = name_
                break
            else:
                self.delPulginName = False
        self.unload_plugin(self.delPulginName)
        del self.delPulginName

    def unload_plugin(self, name):
        if name not in self.plugins:
            return
        plugin = self.plugins.pop(name)
        plugin.deactivate()

    def get_plugins(self):
        return self.plugins


if __name__ == '__main__':
    plugin_manager = PluginManager()

    plugin_manager.load_plugin("model_plugin_1")
    plugin_manager.load_plugin("view_plugin_1")
    plugin_manager.load_plugin("controller_plugin_1")

    plugins = plugin_manager.get_plugins()
    print(plugins)

    plugin_manager.load_plugin("model_plugin_2")
    plugin_manager.load_plugin("view_plugin_2")
    plugin_manager.load_plugin("controller_plugin_2")

    plugins = plugin_manager.get_plugins()
    print(plugins)
